home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / QuickDraw / TranslateRotate / TranslateRotate.p < prev    next >
Encoding:
Text File  |  1992-07-15  |  4.3 KB  |  168 lines  |  [TEXT/MPS ]

  1. {
  2.  
  3. TranslateRotate.p
  4.  
  5.     Many people are uncomfortable with Apple's fixed-point data types,
  6.     because they can't be used with normal operator arithmetic and
  7.     because their representation is not easily readable (though it
  8.     is easily converted to integer types).  Here's something to show
  9.     how simple it really is.
  10.     
  11.     TranslateRotate does two-dimensional translation and rotations
  12.     in word-size coordinates, using fixed-point math.  Each routine
  13.     is passed info for a transform matrix which tells the routine what
  14.     to do with the fPoint argument.  Each routine then does its thing
  15.     on its fPoint argument, returning the new fPoint position.
  16.     
  17.     The purpose of TranslateRotate is to provide a simple demo of the
  18.     use of Fixed and Fract math in basic 2D transformations.  The
  19.     procedures sacrifice speed for clarity in their use of intermediate
  20.     variables, etc.
  21.     
  22.     Fixed-point math has broad applications for speed-sensitive code,
  23.     and is accurate enough for any screen graphics computations, if
  24.     you are careful to perform your computations so as to minimize
  25.     error propagation (do multiplications first, divisions last, for
  26.     example).  There are few reasons to use floating point unless you
  27.     demand error smaller than 2 to the -16.
  28.     
  29.     For demonstration purposes, the two routines (one for rotation,
  30.     one for translation) are called together from an MPW shell
  31.     application.  The application prompts you for x,y translation
  32.     values and a rotation value in radians.  It then calls a routine
  33.     which first rotates and then translates the point.  Type rotation
  34.     = 999 to escape the program.
  35.     
  36.     Points are stored as fWords, which are of size WORD.
  37.  
  38.     Billster
  39.     Apple Computer
  40.     5/10/91
  41.  
  42. }
  43.  
  44. Program TranslateRotate;
  45.  
  46. uses PasLibIntf,FixMath,ToolUtils;
  47.  
  48. const
  49.     FracToIntegerConversion = 1073741824; { Divide by this to turn Frac into truncated int }
  50.     FixToIntegerConversion = 65536; { Divide by this to turn Fixed into truncated int }
  51.  
  52. type
  53.     fWord = integer;                { This is the type for linear measurement hereafter }
  54.     
  55.     fPoint = record                    { This is the type for an arbitrary point }
  56.         x : fWord;
  57.         y : fWord;
  58.     end;
  59.     
  60.     TransRot2D = record                { This record holds all the information for the }
  61.         x : fWord;                    {   transformation or rotation of a point }
  62.         y : fWord;
  63.         rot : Fixed;
  64.     end;
  65.  
  66.     TransRot3D = record                { This would hold the information for the }
  67.         x : fWord;                    {   translation/rotation in the 3D case. }
  68.         y : fWord;                    {   The routines are not implemented in this }
  69.         z : fWord;                    {    sample, however. }
  70.         rotXY : Fixed;
  71.         rotYZ : Fixed;
  72.         rotXZ : Fixed;
  73.     end;
  74.  
  75. var
  76.     transformInput        : transRot2D;
  77.     fPtInput, fPtResult    : fPoint;
  78.  
  79.  
  80.  
  81.  
  82.  
  83. { Routines for translation and rotation }
  84.  
  85.  
  86.  
  87. Function Rotate2D(theFPoint: fPoint; theTransRot : transRot2D) : fPoint;
  88. var
  89.     sinRot, cosRot: Fract;
  90. begin
  91.     sinRot := FracSin(theTransRot.rot);
  92.     cosRot := FracCos(theTransRot.rot);
  93.     
  94.     Rotate2D.x := fWord( FracMul(cosRot,theFPoint.x) - FracMul(sinRot,theFPoint.y) );
  95.     Rotate2D.y := fWord( FracMul(sinRot,theFPoint.x) + FracMul(cosRot,theFPoint.y) );
  96.     
  97.     { The above is a computation of:
  98.         
  99.         | cos(rot)  -sin(rot) |  | x |
  100.         |                      |  |   |
  101.         | sin(rot)  cos(rot)  |  | y |
  102.     }
  103. end;
  104.  
  105.  
  106.  
  107. Function Translate2D(theFPoint: fPoint; theTransRot : transRot2D) : fPoint;
  108. begin
  109.     Translate2D.x := theFPoint.x + theTransRot.x;
  110.     Translate2D.y := theFPoint.y + theTransRot.y;
  111.  
  112.     { The above is a computation of:
  113.         
  114.         | tranlate2D.x       0          |  | x |
  115.         |                               |  |   |
  116.         |      0        tranlate2D.y |  | y |
  117.     }
  118. end;
  119.  
  120.  
  121.  
  122.  
  123.  
  124. { Routines specific to the MPW Shell tool }
  125.  
  126.  
  127. Procedure Initialize;    { Start us off somewhere }
  128. begin
  129.     fPtInput.x := 100;
  130.     fPtInput.y := 100;
  131. end;
  132.  
  133.  
  134.  
  135. Function TransRotate2D(theFPoint: fPoint; theTransRot : transRot2D) : fPoint;
  136. { Calls Rotate2D, then Translate2D }
  137. begin
  138.     TransRotate2D := Translate2D(Rotate2D(theFPoint,theTransRot),theTransRot);
  139. end;
  140.  
  141.  
  142.  
  143. Function GetNext2DTransRot : transRot2D;
  144. { This routine just gets data for the trans/rotate record }
  145. var
  146.     radians : real;
  147. begin
  148.     writeln('X: ');
  149.     readln(GetNext2DTransRot.x);
  150.     writeln('Y: ');
  151.     readln(GetNext2DTransRot.y);
  152.     writeln('Rotation: ');
  153.     readln(radians);
  154.     GetNext2DTransRot.rot := round(radians * FixToIntegerConversion);
  155. end;
  156.  
  157.  
  158.  
  159. begin
  160.     Initialize;
  161.     
  162.     transformInput := GetNext2DTransRot;
  163.     while transformInput.rot <> (999 * FixToIntegerConversion) do begin
  164.         fPtResult := TransRotate2D(fPtInput, transformInput);
  165.         writeln('Output: ',fPtResult.x,fPtResult.y);
  166.         transformInput := GetNext2DTransRot;
  167.     end;
  168. end.